package com.tinyseed.emcp.api.basicdata.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.tinyseed.emcp.api.app.common.Constant;
import com.tinyseed.emcp.api.basicdata.domain.Monitor;
import com.tinyseed.emcp.api.basicdata.domain.Workshop;
import com.tinyseed.emcp.api.basicdata.model.MonitorInputDTO;
import com.tinyseed.emcp.api.basicdata.model.MonitorOutputDTO;
import com.tinyseed.emcp.api.basicdata.model.TreeSelect;
import com.tinyseed.emcp.api.basicdata.repository.EnterpriseRepository;
import com.tinyseed.emcp.api.basicdata.repository.MonitorRepository;
import com.tinyseed.emcp.api.basicdata.repository.WorkshopRepository;
import com.tinyseed.emcp.api.basicdata.service.MonitorService;
import com.tinyseed.hmxx.common.base.PageData;
import com.tinyseed.hmxx.common.utils.QueryHelp;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.swing.text.html.Option;
import java.sql.Timestamp;
import java.util.*;

/***
 * @ClassName: MonitorServiceImpl
 * @Description: TODO
 * @Auther: Harlan.Xiong
 * @Date: 2019-11-24 20:37
 * @version : V1.0
 */
@Service
@CacheConfig(cacheNames = "monitor")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class MonitorServiceImpl implements MonitorService {

    @Autowired
    MonitorRepository monitorRepository;
    @Autowired
    private EnterpriseRepository enterpriseRepository;
    @Autowired
    private WorkshopRepository workshopRepository;

    @Override
    public PageData findAll(MonitorInputDTO monitorInputDTO, Integer page, Integer size) {
        Pageable pageable = PageRequest.of(page - 1, size);
        Page<Monitor> monitors = monitorRepository.findAll((root, criteriaQuery, criteriaBuilder)
                -> getPredicate(monitorInputDTO, root, criteriaBuilder), pageable);
        PageData pageData = new PageData();
        pageData.setTotal(monitors.getTotalElements());
        pageData.setData(monitors.getContent());
        return pageData;
    }

    private Predicate getPredicate(MonitorInputDTO monitorInputDTO, Root<Monitor> root, CriteriaBuilder criteriaBuilder) {
        root.join("workshop", JoinType.LEFT).join("enterprise", JoinType.LEFT);
        List<Predicate> list = new ArrayList<>();

        Optional.ofNullable(monitorInputDTO.getEnterpriseName()).ifPresent(name->{
            Predicate enterpriseNameQuery =
                    criteriaBuilder.and(criteriaBuilder.like(root.get("workshop").get("enterprise").get("enterpriseName"), "%" + monitorInputDTO.getEnterpriseName() + "%"));
            list.add(enterpriseNameQuery);
        });


        return QueryHelp.getPredicate(root, monitorInputDTO, criteriaBuilder,list);
    }

    @Override
    public MonitorOutputDTO findById(Long id) {
        Monitor monitor = monitorRepository.getById(id);
        return monitor.convertToMonitorOutputDTO();
    }

    @Override
    public void deleteById(Long id) {
        monitorRepository.deleteById(id);
    }

    @Override
    public MonitorOutputDTO save(MonitorInputDTO monitorInputDTO) {
        Monitor monitor = new Monitor();
        BeanUtil.copyProperties(monitorInputDTO, monitor);
        Timestamp now = new Timestamp(System.currentTimeMillis());
        if (monitorInputDTO.getCreateTime() == null) {
            monitor.setCreateTime(now);
        }
        monitor.setModifyTime(now);
        Monitor newMonitor = monitorRepository.save(monitor);
        return newMonitor.convertToMonitorOutputDTO();
    }

    @Override
    public List<TreeSelect> getTree() {
        //读取层次数据结果集列表
        List<TreeSelect> treeList = new ArrayList<>();
        //企业信息
        List<Map<String, Object>> enterprises = enterpriseRepository.findEnterprises();
        //车间信息
        List<Workshop> workshops = workshopRepository.findAll();
        if (!CollectionUtils.isEmpty(enterprises)) {
            enterprises.forEach(enterprise -> {
                TreeSelect tree = new TreeSelect();
                tree.setId(Constant.ENTERPRISE_ID_REFIX + enterprise.get("id"));
                tree.setLabel(enterprise.get("enterprise_name").toString());
                tree.setChildren(addChildren(Long.parseLong(enterprise.get("id").toString()), workshops));
                treeList.add(tree);
            });
        }
        return treeList;
    }

    @Override
    public List<MonitorOutputDTO> findAll() {
        List<Monitor> allList = monitorRepository.findAll();
        List<MonitorOutputDTO> resultList = new ArrayList<>(allList.size());
        allList.forEach(item -> {
            MonitorOutputDTO monitorDTO = new MonitorOutputDTO();
            BeanUtils.copyProperties(item, monitorDTO);
            resultList.add(monitorDTO);
        });
        return resultList;
    }

    private List<TreeSelect> addChildren(Long parentId, List<Workshop> workshops) {
        List<TreeSelect> childList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(workshops)) {
            for (Workshop workshop : workshops) {
                if (null != workshop.getEnterpriseId() && parentId.equals(workshop.getEnterpriseId())) {
                    TreeSelect tree = new TreeSelect();
                    tree.setId("" + workshop.getId());
                    tree.setLabel(workshop.getShopName());
                    childList.add(tree);
                }
            }
        }
        return childList;
    }

}
